package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.BookCopyMapper;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.pojo.domain.Book;
import com.zenithmind.library.pojo.domain.BookCopy;
import com.zenithmind.library.pojo.dto.BookCopyCreateDTO;
import com.zenithmind.library.pojo.dto.BookCopyUpdateDTO;
import com.zenithmind.library.pojo.query.BookCopyQuery;
import com.zenithmind.library.pojo.vo.BookCopyVO;
import com.zenithmind.library.service.BookCopyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 图书副本服务实现类
 * 遵循单一职责原则：只负责图书副本相关的业务逻辑
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BookCopyServiceImpl extends ServiceImpl<BookCopyMapper, BookCopy> implements BookCopyService {

    private final BookCopyMapper bookCopyMapper;
    private final BookMapper bookMapper;

    @Override
    @Cacheable(value = "bookCopies", key = "'page:' + #query.hashCode()")
    public PageResult<BookCopyVO> getBookCopyPage(BookCopyQuery query) {
        log.info("分页查询图书副本，查询条件：{}", query);

        // 构建查询条件
        LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();

        if (query.getBookId() != null && !query.getBookId().trim().isEmpty()) {
            wrapper.eq(BookCopy::getBookId, query.getBookId());
        }

        if (query.getBarcode() != null && !query.getBarcode().trim().isEmpty()) {
            wrapper.like(BookCopy::getBarcode, query.getBarcode());
        }

        if (query.getStatus() != null) {
            wrapper.eq(BookCopy::getStatus, query.getStatus());
        }

        if (query.getLocation() != null && !query.getLocation().trim().isEmpty()) {
            wrapper.like(BookCopy::getLocation, query.getLocation());
        }

        wrapper.orderByDesc(BookCopy::getCreateTime);

        // 分页查询
        Page<BookCopy> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<BookCopy> result = page(page, wrapper);

        // 转换为VO
        List<BookCopyVO> vos = result.getRecords().stream()
                                    .map(this::convertToVO)
                                    .collect(Collectors.toList());

        return PageResult.of(vos, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "bookCopies", key = "#id")
    public Result<BookCopyVO> getBookCopyById(String id) {
        log.info("根据ID查询图书副本详情，ID：{}", id);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID不能为空", null);
        }

        BookCopy bookCopy = getById(id);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        BookCopyVO vo = convertToVO(bookCopy);
        return Result.success(vo);
    }

    @Override
    public Result<List<BookCopyVO>> getBookCopiesByBookId(String bookId) {
        log.info("根据图书ID查询所有副本，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookCopy::getBookId, bookId)
               .orderByAsc(BookCopy::getBarcode);

        List<BookCopy> bookCopies = list(wrapper);
        List<BookCopyVO> vos = bookCopies.stream()
                                        .map(this::convertToVO)
                                        .collect(Collectors.toList());

        return Result.success(vos);
    }

    @Override
    @Cacheable(value = "bookCopies", key = "'barcode:' + #barcode")
    public Result<BookCopyVO> getBookCopyByBarcode(String barcode) {
        log.info("根据条形码查询图书副本，条形码：{}", barcode);

        if (barcode == null || barcode.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "条形码不能为空", null);
        }

        LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookCopy::getBarcode, barcode);

        BookCopy bookCopy = getOne(wrapper);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        BookCopyVO vo = convertToVO(bookCopy);
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<BookCopyVO> createBookCopy(BookCopyCreateDTO createDTO) {
        log.info("创建图书副本，参数：{}", createDTO);

        // 验证图书是否存在
        Book book = bookMapper.selectById(createDTO.getBookId());
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        // 检查条形码是否重复
        if (existsByBarcode(createDTO.getBarcode(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "条形码已存在", null);
        }

        BookCopy bookCopy = new BookCopy();
        BeanUtils.copyProperties(createDTO, bookCopy);
        bookCopy.setId(UUID.randomUUID().toString());
        bookCopy.setCreateTime(LocalDateTime.now());
        bookCopy.setUpdateTime(LocalDateTime.now());

        save(bookCopy);

        BookCopyVO vo = convertToVO(bookCopy);
        log.info("图书副本创建成功，ID：{}", bookCopy.getId());
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<List<BookCopyVO>> batchCreateBookCopies(String bookId, Integer quantity) {
        log.info("批量创建图书副本，图书ID：{}，数量：{}", bookId, quantity);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        if (quantity == null || quantity <= 0 || quantity > 100) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "数量必须在1-100之间", null);
        }

        // 验证图书是否存在
        Book book = bookMapper.selectById(bookId);
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        List<BookCopy> bookCopies = new ArrayList<>();
        List<BookCopyVO> vos = new ArrayList<>();

        for (int i = 1; i <= quantity; i++) {
            BookCopy bookCopy = new BookCopy();
            bookCopy.setId(UUID.randomUUID().toString());
            bookCopy.setBookId(bookId);
            bookCopy.setBarcode(generateBarcode(book.getIsbn(), i));
            bookCopy.setStatus(0); // 可借阅
            // 注意：如果BookCopy实体没有enabled字段，这里跳过
            bookCopy.setCreateTime(LocalDateTime.now());
            bookCopy.setUpdateTime(LocalDateTime.now());

            bookCopies.add(bookCopy);
            vos.add(convertToVO(bookCopy));
        }

        saveBatch(bookCopies);

        log.info("批量创建图书副本成功，数量：{}", quantity);
        return Result.success(vos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<BookCopyVO> updateBookCopy(String id, BookCopyUpdateDTO updateDTO) {
        log.info("更新图书副本，ID：{}，参数：{}", id, updateDTO);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID不能为空", null);
        }

        BookCopy bookCopy = getById(id);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        // 检查条形码是否重复
        if (updateDTO.getBarcode() != null && 
            !updateDTO.getBarcode().equals(bookCopy.getBarcode()) &&
            existsByBarcode(updateDTO.getBarcode(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "条形码已存在", null);
        }

        BeanUtils.copyProperties(updateDTO, bookCopy, "id", "bookId", "createTime");
        bookCopy.setUpdateTime(LocalDateTime.now());

        updateById(bookCopy);

        BookCopyVO vo = convertToVO(bookCopy);
        log.info("图书副本更新成功，ID：{}", id);
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<Void> deleteBookCopy(String id) {
        log.info("删除图书副本，ID：{}", id);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID不能为空", null);
        }

        BookCopy bookCopy = getById(id);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        // 检查是否可以删除（不能删除已借出或预约的副本）
        if (bookCopy.getStatus() != null && (bookCopy.getStatus() == 1 || bookCopy.getStatus() == 2)) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "图书副本已借出或预约中，无法删除", null);
        }

        removeById(id);

        log.info("图书副本删除成功，ID：{}", id);
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<Void> batchDeleteBookCopies(List<String> ids) {
        log.info("批量删除图书副本，数量：{}", ids.size());

        if (ids == null || ids.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID列表不能为空", null);
        }

        // 检查所有副本是否可以删除
        for (String id : ids) {
            BookCopy bookCopy = getById(id);
            if (bookCopy == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在：" + id, null);
            }

            if (bookCopy.getStatus() != null && (bookCopy.getStatus() == 1 || bookCopy.getStatus() == 2)) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), 
                    "图书副本《" + bookCopy.getBarcode() + "》已借出或预约中，无法删除", null);
            }
        }

        removeByIds(ids);

        log.info("批量删除图书副本成功，数量：{}", ids.size());
        return Result.success();
    }

    @Override
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<Void> updateBookCopyStatus(String id, Integer status) {
        log.info("更新图书副本状态，ID：{}，状态：{}", id, status);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID不能为空", null);
        }

        BookCopy bookCopy = getById(id);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        bookCopy.setStatus(status);
        bookCopy.setUpdateTime(LocalDateTime.now());
        updateById(bookCopy);

        log.info("图书副本状态更新成功，ID：{}", id);
        return Result.success();
    }

    @Override
    @CacheEvict(value = "bookCopies", allEntries = true)
    public Result<Void> updateBookCopyLocation(String id, String location) {
        log.info("更新图书副本位置，ID：{}，位置：{}", id, location);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书副本ID不能为空", null);
        }

        BookCopy bookCopy = getById(id);
        if (bookCopy == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书副本不存在", null);
        }

        bookCopy.setLocation(location);
        bookCopy.setUpdateTime(LocalDateTime.now());
        updateById(bookCopy);

        log.info("图书副本位置更新成功，ID：{}", id);
        return Result.success();
    }

    @Override
    public boolean existsByBarcode(String barcode, String excludeId) {
        LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookCopy::getBarcode, barcode);
        if (excludeId != null) {
            wrapper.ne(BookCopy::getId, excludeId);
        }
        return count(wrapper) > 0;
    }

    /**
     * 生成条形码
     */
    private String generateBarcode(String isbn, int sequence) {
        return isbn + String.format("%03d", sequence);
    }

    /**
     * 转换为VO对象
     */
    private BookCopyVO convertToVO(BookCopy bookCopy) {
        BookCopyVO vo = new BookCopyVO();
        BeanUtils.copyProperties(bookCopy, vo);

        // 设置关联数据
        try {
            if (bookCopy.getBookId() != null) {
                Book book = bookMapper.selectById(bookCopy.getBookId());
                if (book != null) {
                    vo.setBookTitle(book.getTitle());
                    vo.setBookIsbn(book.getIsbn());
                }
            }

            // 设置状态描述
            vo.setStatusName(getStatusName(bookCopy.getStatus()));

        } catch (Exception e) {
            log.warn("获取图书副本关联数据失败，副本ID：{}", bookCopy.getId(), e);
        }

        return vo;
    }

    /**
     * 获取状态名称
     */
    private String getStatusName(Integer status) {
        if (status == null) {
            return "未知";
        }

        return switch (status) {
            case 0 -> "可借阅";
            case 1 -> "已借出";
            case 2 -> "预约中";
            case 3 -> "维修中";
            case 4 -> "丢失";
            case 5 -> "报废";
            default -> "未知状态";
        };
    }

    @Override
    public Result<BookCopyStatisticsVO> getBookCopyStatistics(String bookId) {
        log.info("获取图书副本统计信息，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        try {
            BookCopyStatisticsVO statistics = new BookCopyStatisticsVO();

            // 统计各种状态的副本数量
            LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BookCopy::getBookId, bookId);

            List<BookCopy> allCopies = list(wrapper);
            statistics.setTotalCopies(allCopies.size());

            // 按状态分组统计
            statistics.setAvailableCopies((int) allCopies.stream().filter(copy -> copy.getStatus() == 0).count());
            statistics.setBorrowedCopies((int) allCopies.stream().filter(copy -> copy.getStatus() == 1).count());
            statistics.setReservedCopies((int) allCopies.stream().filter(copy -> copy.getStatus() == 2).count());
            statistics.setDamagedCopies((int) allCopies.stream().filter(copy -> copy.getStatus() == 3).count());
            statistics.setLostCopies((int) allCopies.stream().filter(copy -> copy.getStatus() == 4).count());

            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取图书副本统计信息失败，图书ID：{}", bookId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "获取统计信息失败", null);
        }
    }

    @Override
    public Result<String> importBookCopies(List<BookCopyCreateDTO> bookCopies) {
        log.info("导入图书副本数据，数量：{}", bookCopies.size());

        if (bookCopies == null || bookCopies.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "导入数据不能为空", null);
        }

        int successCount = 0;
        int failCount = 0;
        StringBuilder errorMessages = new StringBuilder();

        for (int i = 0; i < bookCopies.size(); i++) {
            BookCopyCreateDTO bookCopyDTO = bookCopies.get(i);
            try {
                // 数据验证
                if (bookCopyDTO.getBookId() == null || bookCopyDTO.getBookId().trim().isEmpty()) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：图书ID不能为空；");
                    continue;
                }

                if (bookCopyDTO.getBarcode() == null || bookCopyDTO.getBarcode().trim().isEmpty()) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：条形码不能为空；");
                    continue;
                }

                // 检查条形码是否重复
                if (existsByBarcode(bookCopyDTO.getBarcode(), null)) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：条形码已存在；");
                    continue;
                }

                // 创建图书副本
                Result<BookCopyVO> createResult = createBookCopy(bookCopyDTO);
                if (createResult.isSuccess()) {
                    successCount++;
                } else {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：").append(createResult.getMsg()).append("；");
                }
            } catch (Exception e) {
                failCount++;
                errorMessages.append("第").append(i + 1).append("行：").append(e.getMessage()).append("；");
                log.error("导入第{}行数据失败", i + 1, e);
            }
        }

        String resultMessage = String.format("导入完成，成功：%d条，失败：%d条", successCount, failCount);
        if (failCount > 0) {
            resultMessage += "。失败原因：" + errorMessages.toString();
        }

        log.info("图书副本数据导入完成，成功：{}条，失败：{}条", successCount, failCount);
        return Result.success(resultMessage);
    }

    @Override
    public Result<String> exportBookCopies(BookCopyQuery query) {
        log.info("导出图书副本数据，查询条件：{}", query);

        try {
            // 1. 查询数据
            if (query == null) {
                query = new BookCopyQuery();
            }

            // 设置较大的分页大小以获取所有数据
            query.setSize(10000); // 最多导出10000条记录
            PageResult<BookCopyVO> pageResult = getBookCopyPage(query);

            if (pageResult == null || pageResult.getRecords() == null || pageResult.getRecords().isEmpty()) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有找到符合条件的图书副本数据", null);
            }

            // 2. 生成Excel文件路径
            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = "book_copies_export_" + timestamp + ".xlsx";
            String filePath = "/exports/" + fileName;

            // 3. 这里应该实现实际的Excel生成逻辑
            // 由于没有具体的Excel工具类，这里只是模拟
            log.info("模拟生成Excel文件，包含{}条记录，文件路径：{}", pageResult.getRecords().size(), filePath);

            // 实际项目中，这里应该：
            // - 使用EasyExcel或Apache POI生成Excel文件
            // - 将文件保存到指定目录
            // - 返回文件的访问URL或下载链接

            String resultMessage = String.format("导出成功，共%d条记录，文件：%s",
                pageResult.getRecords().size(), fileName);

            log.info("图书副本数据导出完成，记录数：{}，文件：{}", pageResult.getRecords().size(), fileName);
            return Result.success(resultMessage);

        } catch (Exception e) {
            log.error("导出图书副本数据失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "导出失败：" + e.getMessage(), null);
        }
    }
}
